package com.honey.mybatis.generator;

import java.util.Properties;

import org.java.plugin.PluginLifecycleException;
import org.w3c.dom.Element;

import com.honey.configureation.ConfigurationPlugin;
import com.honey.configureation.holder.ConfigurationHolder;
import com.honey.configureation.holder.ProjectEnvironmentHolder;
import com.honey.configureation.xmlparser.ParseElement;
import com.honey.core.CorePlugin;
import com.honey.core.NullPlugin;
import com.honey.core.calculator.JavaNameCalculator;
import com.honey.core.utils.ObjectFactory;
import com.honey.core.utils.StringUtility;
import com.honey.mybatis.generator.dependent.DependentModel;
import com.honey.mybatis.generator.inversion.InversionModel;

public class MybatisPlugin extends NullPlugin implements ConfigurationHolder{
	private Properties systemProperties;
	
	private String blobSuffix ="WithBLOBs";
	
	/** 注入模型  */
	private InversionModel inversionModel = InversionModel.EXTEND ;
	
	/** 依赖模型  */
	private DependentModel dependentModel = DependentModel.EXTEND;
	
	//entity配置文件
	private String entityTargetPackage="com.honey.undefine.entity";
	
	private String entityClassSuffix ;
	
	private boolean entityTrimStrings =false;
	
	private boolean entitySerializable = true ;
	
	private boolean entityOverrideToString = false;
	
	private boolean entityOverrideToJsonObject = false;
	
	
	private boolean entityFinalMethod=true;
	
	private boolean entityReturnThis=true;
	
	private String enumClassSuffix ="Enum";
	
	
	//dao 配置文件开始
	private String interfaceTargetPackage="com.honey.undefine.dao";
	
	private String interfaceClassSuffix ="Dao";
	
	private boolean interfaceUseSqlSession = false;
	
	
	private String daoInterfacePackage=interfaceTargetPackage;
	
	private String daoInterfaceSuffix=null;
	
	
	private String daoImplementsPackage=interfaceTargetPackage+".imp";
	
	private String daoImplementsSuffix=interfaceClassSuffix+"Imp";
	
	private String baseDaoPackage=daoImplementsPackage;
	
	private String baseDaoName="MybatisBaseDaoSupport";
	
	
	private boolean enableUseSqlSession =false;
	
	private boolean enableInsert = true;
	
	private boolean enableUpdate = true;
	
	private boolean enableDelete = true;
	
	private boolean enableDistinct = false ;
	
	
	//model configuretion
	
	private String modelTargetPackage="com.honey.undefine.model";
	
	private String modelclassSuffix ="Model";
	
	private String modelTableFieldEnumSuffix = "TableField";
	
	//cache configuretion
	private String cacheEviction="LRU";
	private String cacheFlushInterval="60000";
	private String cacheSize="1024";
	private String cacheReadOnly="true";
	private String cacheType=null;
	
	private String mapperTargetPackage = daoImplementsPackage ;
	
	private String mapperfileSuffix = "mapper";
	
	private boolean enableVirtualDeleteKey = true ;
	
	private String connectionTimeOut= "2000";
	
	private JavaNameCalculator javaNameCalculator = null ;
	
	private ProjectEnvironmentHolder projectEnvironmentHolder = null ;
	
	/**
	 * 向CorePlugin申请JavaNameCalculator( 对象映射名称转换器);
	 * @return
	 */
	public JavaNameCalculator getJavaNameCalculator(){
		if(javaNameCalculator == null){
			try {
				CorePlugin corePlugin =(CorePlugin)ObjectFactory.getRequestPlugin(this, "honey.core.plugin");
				javaNameCalculator = corePlugin.getJavaNameCalculator();
			} catch (PluginLifecycleException e) {
				e.printStackTrace();
			}
		}
		return javaNameCalculator;
	}
	
//	public GeneratorJavaClassPlugin getGeneratorJavaClassPlugin(){
//		if( generatorJavaClassPlugin == null ){
//			try {
//				generatorJavaClassPlugin=(GeneratorJavaClassPlugin)ObjectFactory.getRequestPlugin(this, "honey.generator.java.plugin");
//			} catch (PluginLifecycleException e) {
//				e.printStackTrace();
//			}
//		}
//		return generatorJavaClassPlugin;
//	}
	
	public ProjectEnvironmentHolder getProjectEnvironmentHolder(){
		if( projectEnvironmentHolder == null ){
			try {
				projectEnvironmentHolder=
					((ConfigurationPlugin)ObjectFactory.getRequestPlugin(this, "honey.configuration.plugin")
							).getContextInstant().getProjectEnvironmentHolder();
			} catch (PluginLifecycleException e) {
				e.printStackTrace();
			}
		}
		return projectEnvironmentHolder;
	}
	
	@Override
	public void parserElement(Element element, Properties properties) {
		this. systemProperties = properties;
		String tmp =null;
		tmp =  ParseElement.getConfiguration(element, "blobSuffix", properties);
		if(tmp != null) blobSuffix = tmp;
		
		tmp =  ParseElement.getConfiguration(element, "inversionModel", properties);
		if(tmp != null && tmp.equalsIgnoreCase("injection")) inversionModel = InversionModel.INJECTION;
		
		tmp =  ParseElement.getConfiguration(element, "dependentModel", properties);
		if(tmp != null && tmp.equalsIgnoreCase("injection")) dependentModel = DependentModel.INJECTION;
		
		// entity configuretion
		Element ele = ParseElement.getElementsByTagName(element, "javaEntityGenerator");
		if(ele != null){
			tmp = ParseElement.getConfiguration(ele, "targetPackage", properties);
			if(tmp != null)entityTargetPackage =tmp;
			
			tmp = ParseElement.getConfiguration(ele, "classSuffix", properties);
			if(tmp != null)entityClassSuffix =tmp;
			
			entityTrimStrings =StringUtility.isTrue( ParseElement.getConfiguration(ele, "trimStrings", properties) );
			tmp =ParseElement.getConfiguration(ele, "serializable", properties);
			if( tmp == null || StringUtility.isTrue(tmp)){
				this.entitySerializable = true;
			}else{
				this.entitySerializable = false;
			}
			
			tmp =ParseElement.getConfiguration(ele, "enumClassSuffix", properties);
			if(tmp != null)enumClassSuffix = tmp;
			
			tmp =ParseElement.getConfiguration(ele, "overrideToString", properties);
			if( tmp == null || StringUtility.isTrue(tmp)){
				this.entityOverrideToString = true;
			}
			tmp =ParseElement.getConfiguration(ele, "overrideToJson", properties);
			if( tmp == null || StringUtility.isTrue(tmp)){
				this.entityOverrideToJsonObject = true;
			}

			tmp =ParseElement.getConfiguration(ele, "finalMethod", properties);
			if( tmp == null || StringUtility.isTrue(tmp)){
				this.entityFinalMethod = true;
			}else{
				this.entityFinalMethod = false;
			}
			tmp =ParseElement.getConfiguration(ele, "setterReturnThis", properties);
			if(!StringUtility.isTrue(tmp)){
				this.entityReturnThis = false;
			}
			
		}
		// dao configuretion
		ele = ParseElement.getElementsByTagName(element, "javaDaoGenerator");
		if(ele != null){
			tmp = ParseElement.getConfiguration(ele, "targetPackage", properties);
			if(tmp != null)interfaceTargetPackage =tmp;
			
			tmp = ParseElement.getConfiguration(ele, "classSuffix", properties);
			if(tmp != null)interfaceClassSuffix =tmp;
			
			tmp =ParseElement.getConfiguration(ele, "useSqlSession", properties);
			if( tmp == null || StringUtility.isTrue(tmp)){
				this.interfaceUseSqlSession = true;
			}else{
				this.interfaceUseSqlSession = false;
			}
			
			tmp = ParseElement.getConfiguration(ele, "interfacePackage", properties);
			if(tmp != null)daoInterfacePackage =tmp;
			else  daoInterfacePackage = interfaceTargetPackage;
			 
			tmp = ParseElement.getConfiguration(ele, "interfaceSuffix", properties);
			if(tmp != null)daoInterfaceSuffix =tmp;
			else  daoInterfaceSuffix = interfaceClassSuffix;
			
			
			tmp = ParseElement.getConfiguration(ele, "implementsPackage", properties);
			if(tmp != null)daoImplementsPackage =tmp;
			else  daoImplementsPackage = interfaceTargetPackage+".imp";
			 
			tmp = ParseElement.getConfiguration(ele, "implementsSuffix", properties);
			if(tmp != null)daoImplementsSuffix =tmp;
			else  daoImplementsSuffix = interfaceClassSuffix+"Imp";
			
			tmp = ParseElement.getConfiguration(ele, "baseDaoPackage", properties);
			if(tmp != null)baseDaoPackage =tmp;
			
			tmp = ParseElement.getConfiguration(ele, "baseDaoName", properties);
			if(tmp != null)baseDaoName =tmp;
			
			tmp = ParseElement.getConfiguration(ele, "enableUseSqlSession", properties);
			if(tmp != null && StringUtility.isTrue(tmp)){
				enableUseSqlSession=true;
			}else if(tmp != null ){
				enableUseSqlSession=false;
			}
			
			tmp = ParseElement.getConfiguration(ele, "enableInsert", properties);
			if(tmp != null && StringUtility.isTrue(tmp)){
				enableInsert=true;
			}else if(tmp != null ){
				enableInsert=false;
			}
			
			tmp = ParseElement.getConfiguration(ele, "enableUpdate", properties);
			if( tmp != null && StringUtility.isTrue(tmp)){
				enableUpdate=true;
			}else if(tmp != null ){
				enableUpdate=false;
			}
			
			tmp = ParseElement.getConfiguration(ele, "enableDelete", properties);
			if( tmp != null &&  StringUtility.isTrue(tmp)){
				enableDelete=true;
			}else if(tmp != null ){
				enableDelete=false;
			}
		}
		
		//model configuretion
		ele = ParseElement.getElementsByTagName(element, "javaModelGenerator");
		if(ele != null){
			tmp = ParseElement.getConfiguration(ele, "targetPackage", properties);
			if(tmp != null)modelTargetPackage = tmp;
			
			tmp = ParseElement.getConfiguration(ele, "classSuffix", properties);
			if(tmp != null)modelclassSuffix =tmp;
			
			tmp = ParseElement.getConfiguration(ele, "tableFieldEnumSuffix", properties);
			if(tmp != null)modelTableFieldEnumSuffix = tmp;
		}
		
		//mapper configuretion 
		ele = ParseElement.getElementsByTagName(element, "javaMapperGenerator");
		if(ele != null){
			tmp = ParseElement.getConfiguration(ele, "targetPackage", properties);
			if(tmp != null)mapperTargetPackage = tmp;
			
			tmp = ParseElement.getConfiguration(ele, "classSuffix", properties);
			if(tmp != null)mapperfileSuffix = tmp;
			tmp = ParseElement.getConfiguration(ele, "fileSuffix", properties);
			if(tmp != null)mapperfileSuffix = tmp;
			
			tmp = ParseElement.getConfiguration(ele, "connectionTimeOut", properties);
			if(tmp != null){
				try {
					int timeout =Integer.parseInt(tmp);
					if(timeout > 0 ) this.connectionTimeOut =String.valueOf( timeout );
				} catch (NumberFormatException e) {}
			}
			
			tmp = ParseElement.getConfiguration(ele, "enableDistinct", properties);
			if( tmp != null &&  StringUtility.isTrue(tmp)){
				enableDistinct=true;
			}else if(tmp != null ){
				enableDistinct=false;
			}
			
			tmp = ParseElement.getConfiguration(ele, "enableVirtualDeleteKey", properties);
			if( tmp != null &&  StringUtility.isTrue(tmp)){
				enableVirtualDeleteKey=true;
			}else if(tmp != null ){
				enableVirtualDeleteKey=false;
			}

			ele = ParseElement.getElementsByTagName(element, "cache");
			if(ele != null){
				tmp = ParseElement.getConfiguration(ele, "eviction", properties);
				if(tmp != null)cacheEviction = tmp;
				
				tmp = ParseElement.getConfiguration(ele, "flushInterval", properties);
				if(tmp != null)cacheFlushInterval = tmp;
				
				tmp = ParseElement.getConfiguration(ele, "size", properties);
				if(tmp != null)cacheSize = tmp;

				tmp = ParseElement.getConfiguration(ele, "readOnly", properties);
				if(tmp != null)cacheReadOnly = tmp;
				
				tmp = ParseElement.getConfiguration(ele, "type", properties);
				if(tmp != null)cacheType = tmp;	
			}
		}
	}

	@Override
	public String toXmlElement() {
		
		return null;
	}

	@Override
	public void validate() {
		
	}
	
	/**
	 * entity 包名称
	 * @return
	 */
	public String getEntityTargetPackage() {
		return entityTargetPackage;
	}
	
	/**
	 * 从数据库中读取出的字符串类型数据是否去掉字符串的前后空白字符 true:是 false:否
	 * @return
	 */
	public boolean isEntityTrimStrings() {
		return entityTrimStrings;
	}

	public boolean isEntitySerializable() {
		return entitySerializable;
	}

	public String getEnumClassSuffix() {
		return enumClassSuffix;
	}

	public boolean isEntityOverrideToString() {
		return entityOverrideToString;
	}

	public boolean isEntityFinalMethod() {
		return entityFinalMethod;
	}

	public String getEntityClassSuffix() {
		return entityClassSuffix;
	}
	
	public String getModelTargetPackage() {
		return modelTargetPackage;
	}

	public String getModelClassSuffix() {
		return modelclassSuffix;
	}
	
	public String getModelTableFieldEnumSuffix() {
		return modelTableFieldEnumSuffix;
	}

	public boolean isInterfaceUseSqlSession() {
		return interfaceUseSqlSession;
	}

	public String getDaoInterfacePackage() {
		return daoInterfacePackage;
	}

	public String getDaoInterfaceSuffix() {
		return daoInterfaceSuffix;
	}

	public String getDaoImplementsPackage() {
		return daoImplementsPackage;
	}

	public String getDaoImplementsSuffix() {
		return daoImplementsSuffix;
	}

	public String getBlobSuffix() {
		return blobSuffix;
	}

	public String getCacheEviction() {
		return cacheEviction;
	}

	public String getCacheFlushInterval() {
		return cacheFlushInterval;
	}

	public String getCacheSize() {
		return cacheSize;
	}

	public String getCacheReadOnly() {
		return cacheReadOnly;
	}

	public String getCacheType() {
		return cacheType;
	}

	public String getBaseDaoPackage() {
		return baseDaoPackage;
	}

	public String getBaseDaoName() {
		return baseDaoName;
	}

	/**
	 * @return the inversionModel
	 */
	public final InversionModel getInversionModel() {
		return inversionModel;
	}

	/**
	 * @return the dependentModel
	 */
	public final DependentModel getDependentModel() {
		return dependentModel;
	}

	public boolean isEntityReturnThis() {
		return entityReturnThis;
	}

	/**
	 * @return the entityOverrideToJsonObject
	 */
	public boolean isEntityOverrideToJsonObject() {
		return entityOverrideToJsonObject;
	}

	public String getMapperTargetPackage() {
		return mapperTargetPackage;
	}

	public String getMapperfileSuffix() {
		return mapperfileSuffix;
	}

	public String getConnectionTimeOut() {
		return connectionTimeOut;
	}

	public boolean isEnableUseSqlSession() {
		return enableUseSqlSession;
	}

	public boolean isEnableInsert() {
		return enableInsert;
	}

	public boolean isEnableUpdate() {
		return enableUpdate;
	}
	
	public boolean isEnableDelete() {
		return enableDelete;
	}

	public boolean isEnableDistinct() {
		return enableDistinct;
	}

	public boolean isEnableVirtualDeleteKey() {
		return enableVirtualDeleteKey;
	}
}
